#pragma once
#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string>
#include <functional>
#include "handler.hpp"
#include <sys/stat.h>
#include <vector>
#include <fcntl.h>
#include<pthread.h>
#include <sys/wait.h>
#include "loghandler.hpp"
using namespace std;

class sever
{
public:
    typedef function<void(int, uint16_t, string)> func_t;

public:
    sever(uint16_t port, func_t handler)
        : _listensock(-1), _port(port), _handler(handler)
    {
    }
#define defaultip "0.0.0.0"
    void init()
    {
        _listensock = socket(AF_INET, SOCK_STREAM, 0);
        if (_listensock == -1)
        {
            // cerr <<"socket error"<<endl;
            logmessage(FATAL, "listen socket create fail"); // 监听套接字创建失败就是致命错误了
            exit(SOCKET_ERR);
        }
        else
            logmessage(NORMAL, "socket create success");

        // 绑定端口号和ip
        struct sockaddr_in addr;
        addr.sin_family = AF_INET;
        addr.sin_port = htons(_port);
        string ip = defaultip;
        addr.sin_addr.s_addr = inet_addr(ip.c_str());
        socklen_t len = sizeof addr;
        int n = bind(_listensock, (struct sockaddr *)&addr, len);
        if (n == -1)
        {
            // cerr<<"bind error"<<endl;
            logmessage(FATAL, "listen socket bind error");
            exit(BIND_ERR);
        }
        else
            logmessage(NORMAL, "listen socket bind success");
            // cout<<"bind success"<<endl;
#define defaultbacklog 5
        n = listen(_listensock, defaultbacklog);
        if (n == -1)
        {
            // cerr<<"listen err"<<endl;
            logmessage(FATAL, "listen fail");
            exit(LISTEN_ERR);
        }
        else
            logmessage(NORMAL, "listen success");
        // cout<<"listen success"<<endl;
    }

    void start()
    {
        // 死循环从监听套接字中获取新连接
        while (true)
        {
            struct sockaddr_in client;
            socklen_t len = sizeof client;
            int sock = accept(_listensock, (struct sockaddr *)&client, &len);
            if (sock == -1)
            {
                // cerr<<"accept error"<<endl;
                logmessage(FATAL, "accept fail");
                exit(ACCEPT_ERR);
            }
            else
                // cout << "accept a new link , sock :" << sock << endl;
                logmessage(NORMAL,"accept a new link , sock :%d",sock);
            uint16_t clientport = ntohs(client.sin_port);
            string clientip = inet_ntoa(client.sin_addr);
            // version 1
            //_handler(sock,clientport ,clientip);

            // // version 2.1
            // pid_t id = fork();
            // if (id == 0) // 子进程
            // {
            //     close(_listensock);
            //     _handler(sock, clientport, clientip);
            //     //可以手动关闭也可以程序退出自动关闭
            //     close(sock);
            //     exit(0);
            // }
            // // 父进程要wait子进程
            // close(sock);
            // waitpid(id, nullptr, 0); //无法并行
            // // 父进程继续while循环获取新连接

            // // version 2.2
            // static vector<pid_t> ids;
            // pid_t id = fork();
            // if (id == 0) // 子进程
            // {
            //     close(_listensock);
            //     _handler(sock, clientport, clientip);
            //     // 可以手动关闭也可以程序退出自动关闭
            //     close(sock);
            //     exit(0);
            // }
            // ids.push_back(id);
            // // 父进程要wait子进程
            // close(sock);
            // for (int i = 0; i < ids.size(); i++)  //问题是父进程必须 accept 之后才能走到wait的逻辑
            // {
            //     if(ids[i]==waitpid(ids[i],nullptr,WNOHANG))  //说明等待成功
            //     {
            //         ids.erase(ids.begin()+i);
            //         --i;
            //     }
            // }

            // // version 2.3
            // static vector<pid_t> ids;
            // pid_t id = fork();
            // if (id == 0) // 子进程
            // {
            //     if (fork() == 0)
            //         _handler(sock, clientport, clientip); // 孙子进程执行业务逻辑

            //     exit(0); // 子进程和孙子进程都会走这一个退出函数
            // }
            // // 父进程要wait子进程
            // close(sock);
            // waitpid(id, nullptr, 0);

            // // 父进程继续while循环获取新连接

            //version 3  多线程
            pthread_t tid = 0 ;
            ThreadData* pdata = new ThreadData(sock,clientport,clientip);
            int n = pthread_create(&tid,nullptr,start_routine,pdata);
            if(n!=0)  //创建失败
            {
                logmessage(ERROR,"pthread_create fail");  // 一个连接的服务线程失败不影响整个服务器，所以他的级别是ERROR
            }
            (void)n;
        }
    }

private:
    int _listensock;
    uint16_t _port;
    func_t _handler;
};
